package com.haohan.cloud.scm.wms.core.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.haohan.cloud.scm.api.constant.NumberPrefixConstant;
import com.haohan.cloud.scm.api.constant.enums.opc.BuySeqEnum;
import com.haohan.cloud.scm.api.constant.enums.product.ExitStatusEnum;
import com.haohan.cloud.scm.api.constant.enums.product.ProductPlaceStatusEnum;
import com.haohan.cloud.scm.api.constant.enums.product.ProductQialityEnum;
import com.haohan.cloud.scm.api.constant.enums.product.ProductStatusEnum;
import com.haohan.cloud.scm.api.goods.dto.GoodsModelDTO;
import com.haohan.cloud.scm.api.manage.entity.UPassport;
import com.haohan.cloud.scm.api.product.entity.ProductInfo;
import com.haohan.cloud.scm.api.product.feign.ProductInfoFeignService;
import com.haohan.cloud.scm.api.product.req.ProductInfoReq;
import com.haohan.cloud.scm.api.wms.entity.ExitWarehouse;
import com.haohan.cloud.scm.api.wms.entity.ExitWarehouseDetail;
import com.haohan.cloud.scm.api.wms.req.*;
import com.haohan.cloud.scm.api.wms.resp.ExitDetailInfoResp;
import com.haohan.cloud.scm.api.wms.resp.ExitWarehouseDetailResp;
import com.haohan.cloud.scm.api.wms.resp.QueryWaitExitResp;
import com.haohan.cloud.scm.api.wms.trans.ExitWarehouseDetailTrans;
import com.haohan.cloud.scm.api.wms.trans.ExitWarehouseTrans;
import com.haohan.cloud.scm.common.tools.exception.EmptyDataException;
import com.haohan.cloud.scm.common.tools.exception.ErrorDataException;
import com.haohan.cloud.scm.common.tools.util.ScmIncrementUtil;
import com.haohan.cloud.scm.wms.core.IScmExitWarehouseService;
import com.haohan.cloud.scm.wms.service.ExitWarehouseDetailService;
import com.haohan.cloud.scm.wms.service.ExitWarehouseService;
import com.haohan.cloud.scm.wms.utils.ScmWmsUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author xwx
 * @date 2019/6/13
 */
@Service
@AllArgsConstructor
public class ScmExitWarehouseServiceImpl implements IScmExitWarehouseService {

    private final ExitWarehouseDetailService exitWarehouseDetailService;
    private final ExitWarehouseService exitWarehouseService;
    private final ScmIncrementUtil scmIncrementUtil;
    private final ScmWmsUtils scmWmsUtils;
    private final ProductInfoFeignService productInfoFeignService;

    /**
     * 新增出库单 根据出库单明细
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createExitWarehouse(CreateExitWarehouseReq req) {
        //获取出库单申请人对象
        UPassport uPassport = scmWmsUtils.queryUPassportById(req.getPmId());
        ExitWarehouse exitWarehouse = new ExitWarehouse();
        //生成出库单编号
        String sn = scmIncrementUtil.inrcSnByClass(ExitWarehouse.class, NumberPrefixConstant.EXIT_WAREHOUSE_SN_PRE);
        ExitWarehouseDetail exitWarehouseDetail = new ExitWarehouseDetail();
        exitWarehouseDetail.setPmId(req.getPmId());
        //循环查询出库单明细
        for (String exitWarehouseDetailSn : req.getIds()) {
            exitWarehouseDetail.setExitWarehouseDetailSn(exitWarehouseDetailSn);
            ExitWarehouseDetail one = exitWarehouseDetailService.getOne(Wrappers.query(exitWarehouseDetail));
            //判断仓库编号是否一致
            if (!StrUtil.equals(one.getWarehouseSn(), req.getWarehouseSn())) {
                throw new ErrorDataException("仓库编号不一致");
            }
            //设置出库单编号
            one.setExitWarehouseSn(sn);
            exitWarehouseDetailService.updateById(one);
        }
        exitWarehouse.setExitWarehouseSn(sn);
        //设置仓库编号
        exitWarehouse.setWarehouseSn(req.getWarehouseSn());
        //出库状态 待出库
        exitWarehouse.setExitStatus(ExitStatusEnum.wait);
        //出库申请时间
        exitWarehouse.setApplyTime(LocalDateTime.now());
        //出库申请人
        exitWarehouse.setApplicantId(req.getApplicantId());
        exitWarehouse.setApplicantName(uPassport.getLoginName());
        return exitWarehouseService.save(exitWarehouse);
    }

    /**
     * 创建出库单明细(锁库存) 状态:待出货
     *
     * @param detail 出库单明细信息 传入
     * @return 不可锁定库存时 抛出异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExitWarehouseDetail createExitWarehouseDetail(ExitWarehouseDetail detail) {
        String pmId = detail.getPmId();
        String goodsModelId = detail.getGoodsModelId();
        BigDecimal needNum = detail.getProductNumber();
        if(StrUtil.isEmpty(pmId) || StrUtil.isEmpty(goodsModelId)|| null == needNum){
            throw new ErrorDataException("创建出库单明细(锁库存)失败,缺少必需参数");
        }
        // 库存 货品查询
        ProductInfoReq query = new ProductInfoReq();
        query.setPmId(pmId);
        query.setGoodsModelId(goodsModelId);
        query.setProductStatus(ProductStatusEnum.normal);
        query.setProductQuality(ProductQialityEnum.normal);
        query.setProductPlaceStatus(ProductPlaceStatusEnum.stock);
        List list = scmWmsUtils.findProductInfoList(query);
        ProductInfo temp;
        BigDecimal totalNum = BigDecimal.ZERO;
        // 数量用于锁定 的 货品列表
        List<ProductInfo> useList = new ArrayList<>();
        List<String> productSnList = new ArrayList<>();
        for(Object obj:list){
            temp = BeanUtil.toBean(obj, ProductInfo.class);
            totalNum = totalNum.add(temp.getProductNumber());
            useList.add(temp);
            productSnList.add(temp.getProductSn());
            // 判断 数量是否满足 数量
            if(totalNum.compareTo(needNum) > -1){
                break;
            }
        }
        if (totalNum.compareTo(needNum) < 0) {
            throw new ErrorDataException("剩余库存数不足");
        }
        // 锁定库存量
        ProductInfo updateProductInfo = new ProductInfo();
        for(ProductInfo info:useList){
            updateProductInfo.setId(info.getId());
            needNum = needNum.subtract(info.getProductNumber());
            if(BigDecimal.ZERO.compareTo(needNum)<0){
                // 数量全锁定
                updateProductInfo.setProductNumber(BigDecimal.ZERO);
                updateProductInfo.setProductPlaceStatus(ProductPlaceStatusEnum.product);
            }else{
                updateProductInfo.setProductNumber(needNum.abs());
                updateProductInfo.setProductPlaceStatus(ProductPlaceStatusEnum.stock);
            }
            scmWmsUtils.updateProductInfo(updateProductInfo);
        }
        // 出库单使用 最大数量货品的编号, 其余货品编号放入备注
        detail.setProductSn(useList.get(0).getProductSn());
        if(productSnList.size()>1){
            detail.setRemarks(CollUtil.join(productSnList,","));
        }
        detail.setId(null);
        detail.setExitWarehouseDetailSn(null);
        detail.setExitStatus(ExitStatusEnum.wait);
        exitWarehouseDetailService.save(detail);
        return detail;
    }

    /**
     * 确认出库单明细 实出数量
     *
     * @param detail 必需 id/ productNumber
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExitWarehouseDetail confirmExitWarehouseDetail(DetailConfirmRealExitNumReq detail) {
        ExitWarehouseDetail exitWarehouseDetail = exitWarehouseDetailService.getById(detail.getId());
        if (null == exitWarehouseDetail) {
            throw new ErrorDataException("出库单明细有误");
        }
        //状态-> 已接受
        ExitWarehouseDetail update = new ExitWarehouseDetail();
        update.setId(exitWarehouseDetail.getId());
        update.setExitStatus(ExitStatusEnum.receive);
        update.setProductNumber(detail.getProductNumber());
        // 设置出库单编号
        if(StrUtil.isNotEmpty(detail.getExitWarehouseSn())){
            update.setExitWarehouseSn(detail.getExitWarehouseSn());
        }
        // TODO 实际数量拆分对应货品

        String productInfoSn = exitWarehouseDetail.getProductSn();
        ProductInfoReq query = new ProductInfoReq();
        query.setProductSn(productInfoSn);
        ProductInfo productInfo = scmWmsUtils.fetchProductInfo(query);
        ProductInfo updateProductInfo = new ProductInfo();
        updateProductInfo.setId(productInfo.getId());

        // 数量修正
        BigDecimal realNum = detail.getProductNumber();
        BigDecimal initNum = exitWarehouseDetail.getProductNumber();
        BigDecimal stockNum = productInfo.getProductNumber().add(initNum.subtract(realNum));
        updateProductInfo.setProductNumber(stockNum);
        scmWmsUtils.updateProductInfo(updateProductInfo);

        exitWarehouseDetailService.updateById(update);
        return exitWarehouseDetail;
    }

    /**
     * 同一商品 出库 实出数量确认
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean confirmRealExitNum(ConfirmRealExitNumReq req) {
        QueryWrapper<ExitWarehouseDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(ExitWarehouseDetail::getPmId, req.getPmId())
                .eq(ExitWarehouseDetail::getGoodsModelId, req.getGoodsModelId())
                .eq(ExitWarehouseDetail::getExitStatus, ExitStatusEnum.wait);
        List<ExitWarehouseDetail> list = exitWarehouseDetailService.list(queryWrapper);
        if (CollUtil.isEmpty(list)|| CollUtil.isEmpty(req.getDetailList())) {
            return false;
        }
        // 生成出库单编号
        String sn = scmIncrementUtil.inrcSnByClass(ExitWarehouse.class, NumberPrefixConstant.EXIT_WAREHOUSE_SN_PRE);
        // 明细出库
        for (DetailConfirmRealExitNumReq detail : req.getDetailList()) {
            detail.setExitWarehouseSn(sn);
            confirmExitWarehouseDetail(detail);
        }

        ExitWarehouse exitWarehouse = new ExitWarehouse();
        // 出库单属性设置
        exitWarehouse.setExitStatus(ExitStatusEnum.receive);
        exitWarehouse.setWarehouseSn(req.getWarehouseSn());
        exitWarehouse.setExitWarehouseSn(sn);
        exitWarehouseService.save(exitWarehouse);
        return true;
    }

    /**
     *  查询待出库列表
     * @param detail
     * @return
     */
    @Override
    public QueryWaitExitResp queryWaitList(ExitWarehouseDetail detail) {
        QueryWaitExitResp resp = new QueryWaitExitResp();

        // 查询汇总数据 (按商品规格)
        detail.setExitStatus(ExitStatusEnum.wait);
        List<ExitWarehouseDetail> list = exitWarehouseDetailService.summaryExitNum(detail);
        List<ExitDetailInfoResp> infoList = new ArrayList<>(list.size());
        // 返回结果对象
        ExitDetailInfoResp info;
        List<ExitWarehouseDetail> detailList;
        GoodsModelDTO goodsModelDTO;
        String pmId = detail.getPmId();
        for(ExitWarehouseDetail exitDetail:list){
            info = new ExitDetailInfoResp();
            String goodsModelId = exitDetail.getGoodsModelId();
            if(StrUtil.isEmpty(goodsModelId)){
                continue;
            }
            // 查询对应商品的出库单列表
            detail.setGoodsModelId(goodsModelId);
            detail.setDeliveryDate(exitDetail.getDeliveryDate());
            detailList = exitWarehouseDetailService.list(Wrappers.query(detail));
            info.setDetailList(detailList);

            info.setGoodsModelId(goodsModelId);
            info.setProductNumber(exitDetail.getProductNumber());
            info.setDeliveryDate(exitDetail.getDeliveryDate());
            info.setDeliverySeq(detail.getDeliverySeq());
            // 商品
            goodsModelDTO = scmWmsUtils.fetchGoodsModel(goodsModelId);
            // 库存
            ProductInfo productInfo = scmWmsUtils.queryGoodsStorage(pmId, goodsModelId);
            goodsModelDTO.setModelStorage(productInfo.getProductNumber());

            info.setGoodsModel(goodsModelDTO);
            infoList.add(info);
        }
        resp.setList(infoList);
        return resp;
    }

    /**
     * 查询出库单详情（包含货品信息）根据出库单编号
     * @param req
     * @return
     */
    @Override
    public List<ExitWarehouseDetailResp> queryExitWarehouseDetail(QueryExitWarehouseDetailReq req) {
        //查询出库单明细
        ExitWarehouseDetail detail = new ExitWarehouseDetail();
        detail.setPmId(req.getPmId());
        detail.setExitWarehouseSn(req.getExitWarehouseSn());
        List<ExitWarehouseDetail> list = exitWarehouseDetailService.list(Wrappers.query(detail));
        List<ExitWarehouseDetailResp> respList = new ArrayList<>();
        for (ExitWarehouseDetail exitWarehouseDetail : list) {
            //查询货品信息
            ProductInfoReq infoReq = new ProductInfoReq();
            infoReq.setPmId(exitWarehouseDetail.getPmId());
            infoReq.setProductSn(exitWarehouseDetail.getProductSn());
            ProductInfo info = scmWmsUtils.fetchProductInfo(infoReq);
            ExitWarehouseDetailResp resp = ExitWarehouseDetailTrans.respTrans(exitWarehouseDetail, info);
            resp.setExitWarehouseDetailSn(exitWarehouseDetail.getExitWarehouseDetailSn());
            respList.add(resp);
        }
        return respList;
    }

    /**
     * 新增出库单（出库单明细）
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addExitWarehouse(AddExitWarehouseReq req) {
        //生成出库单号
        String sn = scmIncrementUtil.inrcSnByClass(ExitWarehouse.class, NumberPrefixConstant.EXIT_WAREHOUSE_SN_PRE);
        for (GoodsModelReq goodsModelReq : req.getList()) {
            //查询商品库存数量
            ProductInfo info = scmWmsUtils.queryGoodsStorage(req.getPmId(), goodsModelReq.getGoodsModelId());
            if (info.getProductNumber().compareTo(goodsModelReq.getProductNumber())==1 || info.getProductNumber().compareTo(goodsModelReq.getProductNumber())==0){
                //创建出库单明细
                ExitWarehouseDetail exitWarehouseDetail = ExitWarehouseDetailTrans.trans(info);
                exitWarehouseDetail.setPmId(req.getPmId());
                exitWarehouseDetail.setWarehouseSn(req.getWarehouseSn());
                exitWarehouseDetail.setExitType(req.getExitType());
                exitWarehouseDetail.setExitWarehouseSn(sn);
                exitWarehouseDetailService.save(exitWarehouseDetail);
            }else {
                throw new ErrorDataException("库存数量不足");
            }
        }
        //创建出库单
        ExitWarehouse exitWarehouse = ExitWarehouseTrans.trans(req);
        //TODO 申请人
        exitWarehouse.setExitWarehouseSn(sn);
        exitWarehouseService.save(exitWarehouse);
        return true;
    }

    /**
     * 编辑出库单（修改出库单明细）
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean redactExitWarehouse(RedactExitWarehouseReq req) {
        ExitWarehouse warehouse = new ExitWarehouse();
        BeanUtil.copyProperties(req,warehouse);
        if(!exitWarehouseService.updateById(warehouse)){
            return false;
        }
        req.getList().forEach(upd ->{
            ExitWarehouseDetail detail = new ExitWarehouseDetail();
            detail.setExitWarehouseDetailSn(upd.getExitWarehouseDetailSn());
            ExitWarehouseDetail one = exitWarehouseDetailService.getOne(Wrappers.query(detail));
            if(ObjectUtil.isNull(one)){
                throw new EmptyDataException();
            }
            ProductInfo info = scmWmsUtils.queryProductInfo(upd.getProductNumber().intValue(), upd.getGoodsModelId());
            if(info == null){
                throw new EmptyDataException(one.getExitWarehouseSn()+"库存不足");
            }
            one.setProductNumber(upd.getProductNumber());
            if(!exitWarehouseDetailService.updateById(one)){
                throw new ErrorDataException();
            }
        });
        if(!req.getDelList().isEmpty()){
            req.getDelList().forEach(del -> {
                ExitWarehouseDetail detail = new ExitWarehouseDetail();
                detail.setExitWarehouseDetailSn(del.getExitWarehouseDetailSn());
                ExitWarehouseDetail one = exitWarehouseDetailService.getOne(Wrappers.query(detail));
                if(ObjectUtil.isNull(one)){
                    throw new EmptyDataException();
                }
                exitWarehouseDetailService.removeById(one);
            });
        }
        if(!req.getAddList().isEmpty()){
            req.getAddList().forEach(add -> {
                ProductInfo info = scmWmsUtils.queryProductInfo(add.getExitNum(), add.getId());
                if(info == null){
                    throw new EmptyDataException("库存不足");
                }
                ExitWarehouseDetail detail = new ExitWarehouseDetail();
                detail.setProductSn(info.getProductSn());
                detail.setExitStatus(ExitStatusEnum.wait);
                detail.setExitWarehouseSn(req.getExitWarehouseSn());
                detail.setUnit(info.getUnit());
                detail.setProductNumber(BigDecimal.valueOf(add.getExitNum()));
                detail.setGoodsModelId(info.getGoodsModelId());
                detail.setPmId(req.getPmId());
                detail.setDeliveryDate(LocalDate.of(LocalDate.now().getYear(),LocalDate.now().getMonth(),LocalDate.now().getDayOfMonth()+1));
                detail.setDeliverySeq(BuySeqEnum.first);
                detail.setExitType(req.getExitType());
                detail.setApplyTime(LocalDateTime.now());
                if(!exitWarehouseDetailService.save(detail)){
                    throw new ErrorDataException();
                }
            });
        }
        return true;
    }




}
